home *** CD-ROM | disk | FTP | other *** search
- /*
- File: IdleList.cpp
-
- Contains: IdleList and IdleListIterator classes.
-
- Owned by: Christopher Linn
-
- Copyright: © 1993 - 1996 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
-
- <2> 6/14/96 CSL 1257735: Can't register for idle time
- during idle time
- <7> 5/26/95 RR #1251403: Multithreading naming support
- <6> 5/25/95 jpa List.h --> LinkList.h [1253324]
- <5> 4/4/95 RR #1220104 Use if IsEqual , # 1228161
- RegisterIdle updates frequency if called
- twice
- <4> 1/31/95 RR # 1206909 Rewrote AddIdle/RemoveIdle to
- allow unregister while idling, and
- immediate unregister/reregister
- <3> 9/30/94 RR #1167950 Allow unregistering while idling.
- Unregistering simply flags items, and
- RemoveUnregisteredIdlers removes them
- <2> 9/20/94 RR #1154046 Moved ref counting from Dispatcher
- into IdleList methods so that an
- unregistered part is not released.
- <1> 5/13/94 RR first checked in
- <4> 2/7/94 NP Tiger Team doings.
- <3> 12/20/93 RR interface takes part/frame pairs rather
- than frames
- <2> 12/3/93 TÇ Stop including ODError.h, it is included
- as ErrorDef.h inside Except.h
- <1> 11/16/93 RR first checked in
-
- To Do:
- In Progress:
- */
-
- #ifndef _IDLELIST_
- #include "IdleList.h"
- #endif
-
- #ifndef _LINKLIST_
- #include <LinkList.h>
- #endif
-
- #ifndef _FRAME_
- #include "Frame.xh"
- #endif
-
- #ifndef _PART_
- #include "Part.xh"
- #endif
-
- #ifndef _EXCEPT_
- #include "Except.h"
- #endif
-
- #pragma segment IdleList
-
- const ODSLong kMaxLong = 2147483647;
- const ODTicks kMaxIdleFrequency = kMaxLong;
-
- inline long Max(long a, long b)
- {
- return a > b ? a : b;
- }
-
- inline long Min( long a, long b )
- {
- return a < b ? a : b;
- }
-
- //======================================================================================
- // Class IdleInfo
- //======================================================================================
-
- IdleInfo::IdleInfo(ODPart* part, ODFrame* frame, ODIdleFrequency frequency)
- {
- fPart = part;
- fFrame = frame;
- fIdleFrequency = frequency;
- fLastIdle = 0;
- fRemove = kODFalse;
- }
-
- IdleInfo::~IdleInfo()
- {
- }
-
- ODBoolean IdleInfo::NeedsIdle(ODTicks ticks)
- {
- return ( !fRemove && ((ticks - fLastIdle) >= fIdleFrequency));
- }
-
- ODTicks IdleInfo::NextIdle(ODTicks ticks)
- {
- if (fLastIdle == 0)
- return 0;
- else
- return Max(fLastIdle + fIdleFrequency - ticks, 0);
- }
-
-
- //======================================================================================
- // Class IdleList
- //======================================================================================
-
- IdleList::IdleList()
- : fIteratorCount( 0 ),
- fMinIdleFrequency( kMaxIdleFrequency ),
- fMinIdleIsInvalid( kODFalse )
- {
- }
-
- IdleList::~IdleList()
- {
- fImplementation.DeleteAllLinks();
- fDeferredAddedIdlers.DeleteAllLinks();
- }
-
- //-------------------------------------------------------------------------------------
- // IdleList::AddIdle
- //
- // Description
- //-------------------------------------------------------------------------------------
-
- void IdleList::AddIdle(Environment* ev, ODPart* part, ODFrame* frame, ODIdleFrequency frequency)
- {
- IdleInfo* idler = kODNULL;
-
- if ( this->FindIdler( ev, part, frame, &idler ))
- {
- // If it's already there, update the frequency in case it's different
- this->SetIdleFrequency( ev, part, frame, frequency );
- }
- else
- {
- // Not found, make a new idler and add it to the list
- idler = new IdleInfo(part, frame, frequency);
- if (idler)
- {
- if ( fIteratorCount > 0 )
- // Iterators are active, add it to the deferred list
- fDeferredAddedIdlers.AddLast(idler);
- else
- // Safe to add to the active list
- fImplementation.AddLast(idler);
-
- // Aquire references to part & frame
- // These get released in RemoveIdle()
- part->Acquire(ev);
- if (frame)
- frame->Acquire(ev);
-
- fMinIdleFrequency = Min( fMinIdleFrequency, frequency );
- }
- else
- THROW(kODErrOutOfMemory);
- }
- }
-
- //-------------------------------------------------------------------------------------
- // IdleList::RemoveIdle
- //
- // Description
- //-------------------------------------------------------------------------------------
-
- void IdleList::RemoveIdle(Environment* ev, ODPart* part, ODFrame* frame)
- {
-
- IdleInfo* idler = kODNULL;
-
- if ( this->FindIdler( ev, part, frame, &idler ))
- {
- if ( fMinIdleFrequency == idler->GetIdleFrequency())
- fMinIdleIsInvalid = kODTrue;
-
- if ( fIteratorCount > 0 )
- {
- // To allow removal while idling, we just flag
- // "removed" items here.
- // They are cleared by RemoveDeferredIdlers
- idler->SetShouldRemove(kODTrue);
- }
- else
- {
- // No iterators are active, ok to delete
- fImplementation.Remove( *idler );
- delete idler;
- }
-
- part->Release(ev);
- if (frame)
- frame->Release(ev);
- }
- }
-
- //-------------------------------------------------------------------------------------
- // IdleList::RemoveDeferredIdlers
- //
- // Description
- //-------------------------------------------------------------------------------------
-
- void IdleList::RemoveDeferredIdlers()
- {
- // Note that this method does not remove flagged idlers from
- // the deferred added list. Thus, you should call AddDeferredIdlers
- // before calling this method in case there are any idlers on the
- // deferred list that are also flagged for removal. Unlikely, but
- // certainly possible.
- WASSERT( fIteratorCount == 0 );
-
- LinkedListIterator iter(&fImplementation);
-
- for (IdleInfo* link = (IdleInfo*) iter.First();iter.IsNotComplete(); link = (IdleInfo*) iter.Next())
- {
- if (link->ShouldRemove())
- {
- iter.RemoveCurrent();
- delete link;
- }
- }
- }
-
- //-------------------------------------------------------------------------------------
- // IdleList::SetIdleFrequency
- //
- // Description
- //-------------------------------------------------------------------------------------
-
- void IdleList::SetIdleFrequency(Environment* ev, ODPart* part, ODFrame* frame, ODIdleFrequency frequency)
- {
- IdleInfo* idler = kODNULL;
-
- if ( this->FindIdler( ev, part, frame, &idler ))
- {
- // Update the min idle frequency as needed
- if ( fMinIdleFrequency == idler->GetIdleFrequency() && frequency > fMinIdleFrequency )
- fMinIdleIsInvalid = kODTrue;
- else
- fMinIdleFrequency = Min( fMinIdleFrequency, frequency );
-
- // Save the idler's new frequency
- idler->SetIdleFrequency(frequency);
- idler->SetLastIdle(0);
- }
- }
-
-
- //-------------------------------------------------------------------------------------
- // IdleList::IterationBegin
- //
- // Description
- //-------------------------------------------------------------------------------------
-
- void IdleList::IterationBegin()
- {
- ++fIteratorCount;
- }
-
- //-------------------------------------------------------------------------------------
- // IdleList::IterationEnd
- //
- // Description
- //-------------------------------------------------------------------------------------
-
- void IdleList::IterationEnd()
- {
- WASSERT( fIteratorCount > 0 );
-
- if ( --fIteratorCount == 0 )
- {
- // No idlers are currently active, so it's now safe to
- // add and delete idlers that were deferred.
- this->AddDeferredIdlers();
- this->RemoveDeferredIdlers();
- }
- }
-
-
- //-------------------------------------------------------------------------------------
- // IdleList::FindIdler
- //
- // Description
- //-------------------------------------------------------------------------------------
-
- ODBoolean IdleList::FindIdler(Environment* ev, ODPart* part, ODFrame* frame, IdleInfo** idler)
- {
- LinkedListIterator iter(&fImplementation);
- ODBoolean wasFound = kODFalse;
-
- for (IdleInfo* link = (IdleInfo*) iter.First();iter.IsNotComplete(); link = (IdleInfo*) iter.Next())
- {
- // Skip links that are flagged for removal, because their references have been
- // Released, and there may not have been time to clear the flagged links,
- // eg. during Revert
- wasFound = !link->ShouldRemove()
- && ODObjectsAreEqual(ev, link->GetFrame(), frame)
- && ODObjectsAreEqual(ev, link->GetPart(), part);
- if (wasFound)
- {
- *idler = link;
- break;
- }
- }
-
- if ( !wasFound )
- {
- // Continue searching, this time in the list of idlers that have been added during
- // iteration.
- LinkedListIterator iter(&fDeferredAddedIdlers);
-
- for (IdleInfo* link = (IdleInfo*) iter.First();iter.IsNotComplete(); link = (IdleInfo*) iter.Next())
- {
- // Skip links that are flagged for removal, because their references have been
- // Released, and there may not have been time to clear the flagged links,
- // eg. during Revert
- wasFound = !link->ShouldRemove()
- && ODObjectsAreEqual(ev, link->GetFrame(), frame)
- && ODObjectsAreEqual(ev, link->GetPart(), part);
- if (wasFound)
- {
- *idler = link;
- break;
- }
- }
- }
-
- return wasFound;
- }
-
- //-------------------------------------------------------------------------------------
- // IdleList::AddDeferredIdlers
- //
- // Description
- //-------------------------------------------------------------------------------------
-
- void IdleList::AddDeferredIdlers()
- {
- WASSERT( fIteratorCount == 0 );
-
- LinkedListIterator iter( &fDeferredAddedIdlers );
-
- for (IdleInfo* link = (IdleInfo*) iter.First();iter.IsNotComplete(); link = (IdleInfo*) iter.Next())
- {
- iter.RemoveCurrent();
- fImplementation.AddLast( link );
- }
- }
-
-
- //-------------------------------------------------------------------------------------
- // IdleList::GetMinIdleFrequency
- //
- // Description
- //-------------------------------------------------------------------------------------
-
- ODIdleFrequency IdleList::GetMinIdleFrequency()
- {
- if ( fMinIdleIsInvalid )
- {
- LinkedListIterator iter( &fImplementation );
-
- fMinIdleFrequency = kMaxIdleFrequency;
- for (IdleInfo* link = (IdleInfo*) iter.First();iter.IsNotComplete(); link = (IdleInfo*) iter.Next())
- {
- if ( !link->ShouldRemove())
- fMinIdleFrequency = Min( fMinIdleFrequency, link->GetIdleFrequency());
- }
- fMinIdleIsInvalid = kODFalse;
- }
-
- return fMinIdleFrequency;
- }
-
-
- //=====================================================================================
- // IdleListIterator Methods
- //=====================================================================================
-
- //-------------------------------------------------------------------------------------
- // IdleListIterator::IdleListIterator
- //
- // Description
- //-------------------------------------------------------------------------------------
-
- IdleListIterator::IdleListIterator(IdleList* idleList)
- : fIterator(&(idleList->fImplementation))
- {
- fIdleList = idleList;
- fIdleList->IterationBegin();
- }
-
- //-------------------------------------------------------------------------------------
- // IdleListIterator::~IdleListIterator
- //
- // Description
- //-------------------------------------------------------------------------------------
-
- IdleListIterator::~IdleListIterator()
- {
- fIdleList->IterationEnd();
- }
-
- //-------------------------------------------------------------------------------------
- // IdleListIterator::First
- //
- // Description
- //-------------------------------------------------------------------------------------
-
- IdleInfo* IdleListIterator::First()
- {
- return (IdleInfo*) fIterator.First();
- }
-
- //-------------------------------------------------------------------------------------
- // IdleListIterator::Next
- //
- // Description
- //-------------------------------------------------------------------------------------
-
- IdleInfo* IdleListIterator::Next()
- {
- return (IdleInfo*) fIterator.Next();
- }
-
- //-------------------------------------------------------------------------------------
- // IdleListIterator::IsNotComplete
- //
- // Description
- //-------------------------------------------------------------------------------------
-
- ODBoolean IdleListIterator::IsNotComplete()
- {
- return fIterator.IsNotComplete();
- }
-
-